package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.client.feign.CartFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.user.client.feign.UserFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wk
 * @create 2021-09-10 20:40
 */
@RestController
@RequestMapping("/api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private CartFeignClient cartFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderService orderService;

    // 订单列表
    @GetMapping("/getTradeData")
    public Map getTradeData(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        Map map = new HashMap();
        // 1.获取用户收货地址
        List<UserAddress> userAddressList = userFeignClient.findUserAddressList();
        map.put("userAddressList", userAddressList);
        // 2.获取商品订单
        List<CartInfo> cartInfoListByIsChecked = cartFeignClient.findCartInfoListByIsChecked();
        // 使用stream流将被选中商品的集合 转换为 订单的集合
        List<OrderDetail> detailArrayList = cartInfoListByIsChecked.stream().map(cartInfo -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            return orderDetail;
        }).collect(Collectors.toList());
        map.put("detailArrayList", detailArrayList);
        // 3. totalNum总计商品数
        // Collectors.summarizingInt 用来求和订单中商品数量
        long totalNum = detailArrayList.stream().collect(Collectors.summarizingInt(OrderDetail::getSkuNum)).getSum();
        map.put("totalNum", totalNum);
        // 4.totalAmount 总共金额 使用BigDecimal 不会存在精度损失
        BigDecimal totalAmount = new BigDecimal(0);
        for (OrderDetail orderDetail : detailArrayList) {
            totalAmount = totalAmount.add(orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum())));
        }
        map.put("totalAmount", totalAmount);
        // 5.生成订单号
        //  使用时间戳
        //  MD5(userId+盐值) == 交易号
        //  UUID == 交易号  将UUID保存Redis缓存中 删除掉
        //  分布式锁  setnx   setnx(k,v)  如果K存在了 返回值是0 已经提交过了
        //                         只有第一次提交  如果K不存在 返回值是1  未提交过
        long timeInMillis = Calendar.getInstance().getTimeInMillis();
        redisTemplate.opsForValue().set("tradeNo" + userId, timeInMillis);
        map.put("tradeNo", timeInMillis);
        return map;
    }

    // 提交订单 /auth/submitOrder?tradeNo
    @PostMapping("/auth/submitOrder") // 页面规定post请求  /auth/submitOrder/{xx}     @PathVariable  x xx
    public Result submitOrder(@RequestBody OrderInfo orderInfo, Long tradeNo, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        // 获取缓存中的订单流水号
        Long redisTradeNo = (Long) redisTemplate.opsForValue().get("tradeNo" + userId);
        // 1.判断订单号是否相等
        if (tradeNo.equals(redisTradeNo)) {
            // 2.交易号相等 先将缓存中的流水号进行删除
            redisTemplate.delete("tradeNo" + userId);
            // 3.判断库存 如果库存量够 则 继续完成订单提交 否则 进行提示
            List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
            // 对订单列表中的订单库存进行遍历判断
            for (OrderDetail orderDetail : orderDetailList) {
                // 库存服务返回结果 如果又则返回1 否则返回0
                boolean flag = orderService.hasStock(orderDetail);
                if (!flag) {
                    // 如果返回false 则表示没货
                    return Result.fail().message(orderDetail.getSkuName() + "此款商品库存不足");
                }
            }
            // 4.保存订单
            orderInfo.setUserId(Long.parseLong(userId));
            Long orderId = orderService.saveOrder(orderInfo);
            return Result.ok(orderId);
        } else {
            return Result.fail().message("请不要重复提交");
        }
    }

    // 查询订单详细信息
    @GetMapping("/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable Long orderId) {
        return orderService.getOrderInfo(orderId);
    }
}
